package com.future.exception;

import com.future.domain.Result;
import org.omg.CORBA.SystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

@RestControllerAdvice  //返回json而非视图
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);



    @ExceptionHandler(ServiceException.class)
    public Result handleServiceException(ServiceException ex, HttpServletRequest request) {
        //方便记录具体异常信息，项目上线时删除
        ex.printStackTrace();
        // 记录警告日志（业务异常通常不需要记录错误级别）
        logger.warn("业务异常 [path={}] {}",
                request.getRequestURI(), ex.getMessage());


        return Result.fail(ex.getMessage());
    }

    // 处理业务异常
    @ExceptionHandler(BusinessException.class)
    public Result handleBusinessException(BusinessException ex) {
        //方便记录具体异常信息，项目上线时删除
        ex.printStackTrace();
        // 记录警告日志（业务异常通常不需要记录错误级别）
        logger.warn("业务异常 [code={}, path={}] {}",
                ex.getErrorCode(),
                ex.getMessage());


        return Result.fail(ex.getErrorMessage());
    }

    // 处理系统异常
    @ExceptionHandler(SystemException.class)
    public Result handleSystemException(SystemException ex) {
        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        // 记录错误日志（包含异常堆栈）
        logger.error("系统异常 [code={}, path={}]",
                ex.getMessage(),
                ex);

        return Result.fail(ex.getMessage());
    }

    // 处理参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidationException(MethodArgumentNotValidException ex
                                                  ) {
        BindingResult result = ex.getBindingResult();
        List<String> errors = result.getFieldErrors().stream()
                .map(f -> f.getField() + ": " + f.getDefaultMessage())
                .collect(Collectors.toList());

        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        // 记录校验失败详情
        logger.info("参数校验失败 [path={}] {}", errors);


        return Result.fail(ex.getMessage());
    }

    // 处理404异常
    @ExceptionHandler(NoHandlerFoundException.class)
    public Result handleNotFound(NoHandlerFoundException ex) {
        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();
        logger.warn("404异常 [method={}, path={}]",
                ex.getHttpMethod(),
                ex.getRequestURL());


        // 如果404页面是API请求，可以重定向到首页
        return Result.fail(ex.getMessage());
    }

    // 处理全局未分类异常
    @ExceptionHandler(Exception.class)
    public Result handleGlobalException(Exception ex,
                                              HttpServletRequest request
                                             ) {
        //方便记录具体异常信息，项目上线时最好删除
        ex.printStackTrace();

        return Result.fail(ex.getMessage());
    }
}